package com.codemonkey.lq.qd.builder.xml;

import java.util.Properties;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.parsing.XNode;

import com.codemonkey.lq.qd.builder.BaseBuilder;
import com.codemonkey.lq.qd.facotry.config.AbstractActionDefinition;
import com.codemonkey.lq.qd.facotry.config.AbstractServiceDefinition;
import com.codemonkey.lq.qd.facotry.config.SConfiguration;
import com.codemonkey.lq.qd.facotry.config.executer.ActionHandler;
import com.codemonkey.lq.qd.facotry.support.GenericActionDefinition;
import com.codemonkey.lq.qd.utils.StringHelper;

/**
 * @author LQ
 */
public class XMLActionBuilder extends BaseBuilder {
	
	/*
	 * 之所以放在这里,而没有放在ActionDefinition接口中:
	 * 	  仿造Spring,其并未将xml中对应节点和属性的字符串名称放在BeanDefinition中.而是放在了进行转换的BeanDefinitionParserDelegate类中
	 *    Spring的BeanDefinition是get/set都具备的;之前鄙人的理解是接口中放get,而在实现接口的Abstractxxx中放置set.
	 * */
	
	public static final String NAME_ATTRIBUTE = "name";
	
	public static final String SQLID_ATTRIBUTE = "sqlId";
	
	/**
	 * 直接取之于org.apache.ibatis.mapping.SqlCommandType
	 */
	public static final String SQLTYPE_ATTRIBUTE = "sqlType";
	
	public static final String RESULT_ATTRIBUTE = "result";
	
	public static final String RESULTTYPE_ATTRIBUTE = "resultType";
	
	public static final String ISPAGE_ATTRIBUTE = "isPage";
	
	public static final String PARAMETER_ATTRIBUTE = "parameter";
	
	public static final String CONDITION_ATTRIBUTE = "condition";
	
	public static final String HANDLER_ATTRIBUTE = "handler";
	

	
	private XNode context;
	private final AbstractServiceDefinition sd;

	public XMLActionBuilder(XNode context, AbstractServiceDefinition sd,
			SConfiguration configuration) {
		super(configuration);
		this.context = context;
		this.sd = sd;
	}

	@Override
	protected Object doParse() {
		String name = context.getStringAttribute(NAME_ATTRIBUTE);
		Properties props = context.getChildrenAsProperties();

		GenericActionDefinition sa = new GenericActionDefinition(sd);
		//sa.setParentSD(sd);
		
		sa.setName(name);
		sa.setSqlId(props.getProperty(SQLID_ATTRIBUTE));
		sa.setSqlType(props.getProperty(SQLTYPE_ATTRIBUTE));
		sa.setResult(props.getProperty(RESULT_ATTRIBUTE));
		sa.setResultType(props.getProperty(RESULTTYPE_ATTRIBUTE));
		sa.setPage(Boolean.parseBoolean(props.getProperty(ISPAGE_ATTRIBUTE)));
		sa.setParameter(props.getProperty(PARAMETER_ATTRIBUTE));
		sa.setCondition(props.getProperty(CONDITION_ATTRIBUTE));

		setHandler(sa, props);
		

		sd.addAction(sa);
		
		return sa;
	}

	private void setHandler(AbstractActionDefinition sa, Properties props) {
		String handlerStr = props.getProperty(HANDLER_ATTRIBUTE);

		if (StringHelper.isEmpty(handlerStr)) {
			return;
		}

		ActionHandler handler = null;
		try {
			handler = (ActionHandler) Resources.classForName(handlerStr).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		if (handler == null) {
			String errorInfo = String.format("the class '%s' does not exist or not implement ActionHandler interface", handlerStr);
			throw new IllegalArgumentException(errorInfo);
		}
		

		sa.setHandler(handler);
	}
	
	
}
